import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import WipBadRegistration from '@main/entities/service/admin/wip/wip-bad-registration.entity';
import WipBadRegistrationList from '@main/entities/service/admin/wip/wip-bad-registration-list.entity';
import { In, Repository, Brackets } from 'typeorm';
import { BaseBadService } from '@main/service/modules/admin/base/bad/bad.service';
import { UtilService } from '@main/shared/services/util.service';
import BaseBad from '@main/entities/service/admin/base/base-bad.entity';
import { ApiException } from '@main/common/exceptions/api.exception';
import { generateExcelFn } from '@main/excel';
import { SysOperationLogService } from '../../system/operationLog/operationLog.service';

@Injectable()
export class WipBadRegistrationService {
  constructor(
    @InjectRepository(WipBadRegistration)
    private badRegistrationRepository: Repository<WipBadRegistration>,
    @InjectRepository(WipBadRegistrationList)
    private badRegistrationListRepository: Repository<WipBadRegistrationList>,
    @InjectRepository(BaseBad)
    private badRepository: Repository<BaseBad>,
    private baseBadService: BaseBadService,
    private util: UtilService,
    private operationLogService: SysOperationLogService
  ) {}

  /**
   * 列举所有角色：除去超级管理员
   */
  async list() {
    const badRegistrationList = await this.badRegistrationRepository.find();

    await Promise.all(
      badRegistrationList.map(async (badRegistration) => {
        const { badRegistrationCode } = badRegistration;
        const badRegistrationList = await this.badRegistrationListRepository.find({
          where: { badRegistrationCode },
        });

        badRegistration['badRegistrationList'] = badRegistrationList;
      })
    );

    return badRegistrationList;
  }

  /**
   * 分页加载不良登记信息
   */
  async page(data) {
    const { pageSize, pageNum, entity = {} } = data;

    const {
      fastSearch = '',
      shiftCode = '',
      registrationStartTime = '',
      registrationEndTime = '',
    } = entity;

    // 创建查询构造器
    const queryBuilder = this.badRegistrationRepository
      .createQueryBuilder('wip_bad_registration') // 主表别名
      .leftJoinAndSelect('wip_bad_registration.badRegistrationList', 'badRegistrationList') // 联接子表
      .orderBy('wip_bad_registration.updateTime', 'DESC'); // 排序

    // 处理时间范围查询条件
    if (registrationStartTime && registrationEndTime) {
      queryBuilder.andWhere('wip_bad_registration.create_time BETWEEN :start AND :end', {
        start: registrationStartTime,
        end: registrationEndTime,
      });
    }

    // 处理 shiftCode 查询条件
    if (shiftCode) {
      queryBuilder.andWhere('wip_bad_registration.shift_code = :shiftCode', { shiftCode });
    }

    // 处理 fastSearch 模糊查询
    if (fastSearch) {
      queryBuilder.andWhere(
        new Brackets((qb) => {
          qb.where('wip_bad_registration.material_name LIKE :fastSearch', {
            fastSearch: `%${fastSearch}%`,
          })
            .orWhere('wip_bad_registration.material_code LIKE :fastSearch', {
              fastSearch: `%${fastSearch}%`,
            })
            .orWhere('wip_bad_registration.order_code LIKE :fastSearch', {
              fastSearch: `%${fastSearch}%`,
            })
            .orWhere('wip_bad_registration.custom_name LIKE :fastSearch', {
              fastSearch: `%${fastSearch}%`,
            })
            .orWhere('wip_bad_registration.custom_short LIKE :fastSearch', {
              fastSearch: `%${fastSearch}%`,
            })
            .orWhere('wip_bad_registration.custom_code LIKE :fastSearch', {
              fastSearch: `%${fastSearch}%`,
            });
        })
      );
    }

    // 分页查询
    queryBuilder.skip((pageNum - 1) * pageSize).take(pageSize);

    // 执行查询
    const [list, total] = await queryBuilder.getManyAndCount();

    return [list, total];
  }

  async export(dto, lang) {
    const [list] = await this.page(dto);

    if (!list || !(list as any).length) {
      throw new ApiException(10052);
    }

    const dataList = (list as any).map((item) => ({
      ...item,
      list: item.badRegistrationList || [],
    }));

    return await generateExcelFn(
      {
        sheetName: 'badRegistration',
        mainHeaderList: [
          {
            label: 'badRegistrationCode',
          },
          {
            label: 'orderCode',
          },
          {
            label: 'erpNo',
          },
          {
            label: 'machineName',
          },
          {
            label: 'machineCode',
          },
          {
            label: 'materialCode',
          },
          {
            label: 'materialName',
          },
          {
            label: 'version',
          },
          {
            label: 'customName',
          },
          {
            label: 'shiftName',
          },
          {
            label: 'orderNum',
          },
          {
            label: 'remark',
          },
        ],
        childHeadersName: 'badRegistrationListTableName',
        childHeaderList: [
          {
            label: 'badName',
          },
          {
            label: 'badCode',
          },
          {
            label: 'badLevelName',
          },
          {
            label: 'badNum',
          },
        ],
        dataList,
      },
      lang
    );
  }

  /**
   * 处理岗位逻辑，如果是新增岗位，则调用岗位新增方法
   */
  async handleBadRegistration(badRegistrationList, user, mac, ip, syncHostSqlite) {
    for (let i = 0; i < badRegistrationList.length; i++) {
      const { badCode, badName, badLevelCode } = badRegistrationList[i];

      const result = await this.badRepository.findOne({
        where: { badCode },
      });

      if (!result) {
        await this.baseBadService.add(
          {
            badName,
            badCode,
            badLevelCode,
          },
          user,
          mac,
          ip,
          syncHostSqlite
        );
      }
    }
  }

  /**
   * 增加不良登记
   */
  async add(data, user, mac, ip, syncHostSqlite) {
    const databaseOperationLogList = [];
    const databaseOperationLogList1 = [];

    const {
      orderCode,
      erpNo,
      machineCode,
      materialCode,
      materialName,
      customCode,
      customShort,
      customName,
      orderNum,
      shiftCode,
      shiftName,
      remark,
      badRegistrationList,
      materialLength,
      materialWidth,
      materialHeight,
      scheduledStartTime,
      scheduledEndTime,
      version,
    } = data;

    const badRegistrationCode = `BL${this.util.nowDateValue()}${this.util.generateRandomNumberValue(
      4
    )}`;

    const result = await this.badRegistrationRepository.find({ where: { badRegistrationCode } });

    if (result && result.length) {
      this.add(data, user, mac, ip, syncHostSqlite);

      return;
    }

    await this.handleBadRegistration(badRegistrationList, user, mac, ip, syncHostSqlite);

    const badRegistration = await this.badRegistrationRepository.insert({
      version,
      badRegistrationCode,
      orderCode,
      erpNo,
      machineCode,
      materialCode,
      materialName,
      customCode,
      customShort,
      customName,
      orderNum,
      shiftCode,
      shiftName,
      materialLength,
      materialWidth,
      materialHeight,
      scheduledStartTime,
      scheduledEndTime,
      remark,
      createName: user.nickName,
      createUserName: user.userName,
      updateName: user.nickName,
      updateUserName: user.userName,
    });

    databaseOperationLogList.push({
      type: 'add',
      dataType: 'obj',
      database: 'WipBadRegistration',
      checkOnlyKeyList: [],
      data: badRegistration,
      whereObj: null,
      remark: `WipBadRegistration表新增数据`,
    });
    await this.operationLogService.add(
      {
        type: 'add',
        msg: `不良登记管理模块新增不良登记`,
        databaseOperationLogList,
        remark: `新增不良登记编号${data.badRegistrationCode}`,
        mac,
        ip,
        syncHostSqlite: isNaN(Number(syncHostSqlite)) ? 0 : Number(syncHostSqlite),
      },
      user
    );
    const badRegistrationList1 = await this.badRegistrationListRepository.insert(
      badRegistrationList.map((item) => ({ ...item, badRegistrationCode }))
    );
    databaseOperationLogList1.push({
      type: 'add',
      dataType: 'obj',
      database: 'WipBadRegistrationList',
      checkOnlyKeyList: [],
      data: badRegistrationList1,
      whereObj: null,
      remark: `WipBadRegistrationList表新增数据`,
    });
    await this.operationLogService.add(
      {
        type: 'add',
        msg: `不良登记管理模块产品不良信息新增产品不良信息`,
        databaseOperationLogList1,
        remark: `新增产品不良信息`,
        mac,
        ip,
        syncHostSqlite: isNaN(Number(syncHostSqlite)) ? 0 : Number(syncHostSqlite),
      },
      user
    );
  }

  /**
   * 更新不良登记信息
   */
  async update(data, user, mac, ip, syncHostSqlite) {
    const databaseOperationLogList = [];

    const { id, shiftCode, shiftName, remark, badRegistrationList, badRegistrationCode } = data;

    await this.handleBadRegistration(badRegistrationList, user, mac, ip, syncHostSqlite);

    await this.badRegistrationRepository.update(
      { id },
      {
        shiftName,
        shiftCode,
        remark,
        updateName: user.nickName,
        updateUserName: user.userName,
      }
    );
    databaseOperationLogList.push({
      type: 'update',
      dataType: 'obj',
      database: 'WipBadRegistration',
      checkOnlyKeyList: [],
      data: {
        shiftName,
        shiftCode,
        remark,
        updateName: user.nickName,
        updateUserName: user.userName,
      },
      whereObj: { id },
      remark: `WipBadRegistration表更新不良登记信息`,
    });
    await this.operationLogService.add(
      {
        type: 'update',
        msg: `不良登记管理模块更新不良登记信息`,
        databaseOperationLogList,
        remark: `更新不良登记编号${data.badRegistrationCode}`,
        mac,
        ip,
        syncHostSqlite: isNaN(Number(syncHostSqlite)) ? 0 : Number(syncHostSqlite),
      },
      user
    );

    if (badRegistrationList && badRegistrationList.length) {
      await this.badRegistrationListRepository.delete({
        badRegistrationCode,
      });

      const newList = badRegistrationList.map((item) => ({ ...item, badRegistrationCode }));

      console.log(newList);

      await this.badRegistrationListRepository.insert(newList);
    }
  }

  /**
   * 根据Id数组删除不良登记
   */
  async delete(idList, user, mac, ip, syncHostSqlite) {
    const databaseOperationLogList = [];
    const databaseOperationLogList1 = [];

    const badRegistrationList = await this.badRegistrationRepository.find({
      where: {
        id: In(idList),
      },
    });

    for (let i = 0; i < badRegistrationList.length; i++) {
      const { badRegistrationCode } = badRegistrationList[i];

      await this.badRegistrationListRepository.delete({ badRegistrationCode });
      databaseOperationLogList1.push({
        type: 'delete',
        dataType: 'array',
        database: 'WipBadRegistrationList',
        checkOnlyKeyList: [],
        data: null,
        whereObj: idList,
        remark: `WipBadRegistrationList表删除产品不良信息(删除时)`,
      });
      await this.operationLogService.add(
        {
          type: 'delete',
          msg: `(删除时)不良登记管理模块产品不良信息删除产品不良信息`,
          databaseOperationLogList1,
          remark: `删除产品不良信息`,
          mac,
          ip,
          syncHostSqlite: isNaN(Number(syncHostSqlite)) ? 0 : Number(syncHostSqlite),
        },
        user
      );
    }

    await this.badRegistrationListRepository.delete(idList);

    databaseOperationLogList.push({
      type: 'delete',
      dataType: 'array',
      database: 'WipBadRegistration',
      checkOnlyKeyList: [],
      data: null,
      whereObj: idList,
      remark: `WipBadRegistration表删除不良登记信息`,
    });
    await this.operationLogService.add(
      {
        type: 'delete',
        msg: `不良登记管理模块删除不良登记信息`,
        databaseOperationLogList,
        remark: `删除不良登记信息`,
        mac,
        ip,
        syncHostSqlite: isNaN(Number(syncHostSqlite)) ? 0 : Number(syncHostSqlite),
      },
      user
    );
  }

  /**
   * 根据id获取不良登记信息
   */
  async info(id) {
    const badRegistration = await this.badRegistrationRepository.findOne({
      where: { id },
    });

    if (badRegistration) {
      const { badRegistrationCode } = badRegistration;

      const badRegistrationList = await this.badRegistrationListRepository.find({
        where: { badRegistrationCode },
      });

      badRegistration['badRegistrationList'] = badRegistrationList;

      return badRegistration;
    }
  }
}
